#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include "imbus_internal.h"
#include "im_value.h"
#include "im_value_impl.h"

/************************** Declaration of internal functions ***************/
static void     __im_value_initialize   (IMPointer      value);
static void     __im_value_finalize     (IMPointer      value);
static void     __im_value_copy         (IMPointer      dest,
                                         IMConstPointer src);
static IMBool   __im_value_serialize    (IMConstPointer obj,
                                         IMPointer      stream);
static IMBool   __im_value_deserialize  (IMPointer      obj,
                                         IMPointer      stream);
static void     __im_value_class_init   (IMPointer      klass);

/****************** Declaration of object and class structure ************/
struct _IMValue
{
    IMObject object;
    IMValueImpl impl;
};

struct _IMValueClass
{
    IMObjectClass parent_class;
};

/************************ Internal varable ************************/
static const IMObjectClass *__im_value_parent_class = 0;

/************* Implementation of internal functions ***************/
static void
__im_value_initialize (IMPointer value)
{
    im_value_impl_init (&((IMValue*)value)->impl);
}

static void
__im_value_finalize (IMPointer value)
{
    im_value_impl_clear(&((IMValue*)value)->impl);
}

static void
__im_value_copy (IMPointer dest, IMConstPointer src)
{
    IMValue       *dvp = IM_VALUE (dest);
    const IMValue *svp = IM_CONST_VALUE (src);

    _im_assert (dvp && svp);

    im_value_impl_copy(&dvp->impl, &svp->impl);

    /* Call copy method of parent class */
    __im_value_parent_class->copy (dest, src);
}

static IMBool
__im_value_serialize (IMConstPointer obj, IMPointer stream)
{
    const IMValue *vp = IM_CONST_VALUE (obj);
    IMStream      *sp = IM_STREAM (stream);

    _im_assert (vp && sp);

    /* Call parent serialize method */
    return __im_value_parent_class->serialize (obj, stream) &&
           __im_value_impl_serialize (&vp->impl, sp);
}

static IMBool
__im_value_deserialize (IMPointer obj, IMPointer stream)
{
    IMValue  *vp = IM_VALUE (obj);
    IMStream *sp = IM_STREAM (stream);

    _im_assert (vp && sp);

    /* Call parent deserialize method */
    if (!__im_value_parent_class->deserialize (obj, stream))
        return FALSE;

    return __im_value_impl_deserialize (&vp->impl, sp);
}

static void
__im_value_class_init (IMPointer klass)
{
    IMObjectClass *cp = (IMObjectClass *)klass;

    cp->copy        = __im_value_copy;
    cp->serialize   = __im_value_serialize;
    cp->deserialize = __im_value_deserialize;

    __im_value_parent_class = im_object_class_get_parent (cp);
}

/************* Implementation of public functions ***************/
void
__im_type_register_value ()
{
    static IMTypeInfo im_value_type_info = 
    {
        sizeof (IMValueClass),      /**< class_size >**/
        __im_value_class_init,      /**< class_init >**/
        0,                          /**< class_finalize >**/

        sizeof (IMValue),           /**< instance_size >**/
        __im_value_initialize,      /**< instance_init >**/
        __im_value_finalize,        /**< instance_finalize >**/
    };

    __im_type_register_builtin_class (IM_TYPE_OBJECT,
                                      IM_TYPE_VALUE,
                                      "Value",
                                      &im_value_type_info,
                                      TRUE);
}

IMValue*
im_value_new ()
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    return v;
}
IMValue*
im_value_new_char (IMChar v_char)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_char (&v->impl, v_char);
    return v;
}
IMValue*
im_value_new_uchar (IMUChar v_uchar)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_uchar (&v->impl, v_uchar);
    return v;
}
IMValue*
im_value_new_bool (IMBool v_bool)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_bool (&v->impl, v_bool);
    return v;
}
IMValue*
im_value_new_int16 (IMInt16 v_int16)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_int16 (&v->impl, v_int16);
    return v;
}
IMValue*
im_value_new_uint16 (IMUInt16 v_uint16)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_uint16 (&v->impl, v_uint16);
    return v;
}
IMValue*
im_value_new_int32 (IMInt32 v_int32)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_int32 (&v->impl, v_int32);
    return v;
}
IMValue*
im_value_new_uint32 (IMUInt32 v_uint32)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_uint32 (&v->impl, v_uint32);
    return v;
}
IMValue*
im_value_new_int64 (IMInt64 v_int64)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_int64 (&v->impl, v_int64);
    return v;
}
IMValue*
im_value_new_uint64 (IMUInt64 v_uint64)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_uint64 (&v->impl, v_uint64);
    return v;
}
IMValue*
im_value_new_double (IMDouble v_double)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_double (&v->impl, v_double);
    return v;
}
IMValue*
im_value_new_pointer (IMPointer v_pointer)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_pointer (&v->impl, v_pointer);
    return v;
}
IMValue*
im_value_new_c_string (const IMChar *v_string)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_c_string (&v->impl, v_string);
    return v;
}
IMValue*
im_value_new_static_c_string(const IMChar *v_string)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_static_c_string (&v->impl, v_string);
    return v;
}
IMValue*
im_value_new_take_c_string (IMChar *v_string)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_take_c_string (&v->impl, v_string);
    return v;
}
IMValue*
im_value_new_object (IMPointer v_object)
{
    IMValue *v = (IMValue *) im_object_new (IM_TYPE_VALUE);
    _im_assert (v != 0);
    im_value_impl_set_object (&v->impl, v_object);
    return v;
}

IMType
im_value_get_value_type (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE(value), IM_TYPE_INVALID);
    return im_value_impl_value_type(&value->impl);
}

void
im_value_clear (IMValue *value)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_clear(&value->impl);
}

void
im_value_set_char (IMValue *value, IMChar v_char)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_char (&value->impl, v_char);
}

IMChar
im_value_get_char (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_char (&value->impl);
}

void
im_value_set_uchar (IMValue *value, IMUChar v_uchar)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_uchar (&value->impl, v_uchar);
}

IMUChar
im_value_get_uchar (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_uchar (&value->impl);
}

void
im_value_set_bool (IMValue *value, IMBool v_bool)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_bool (&value->impl, v_bool);
}

IMBool
im_value_get_bool (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), FALSE);
    return im_value_impl_get_bool (&value->impl);
}

void
im_value_set_int16 (IMValue *value, IMInt16 v_int16)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_int16 (&value->impl, v_int16);
}

IMInt16
im_value_get_int16 (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_int16 (&value->impl);
}

void
im_value_set_uint16 (IMValue *value, IMUInt16 v_uint16)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_uint16 (&value->impl, v_uint16);
}

IMUInt16
im_value_get_uint16 (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_uint16 (&value->impl);
}

void
im_value_set_int32 (IMValue *value, IMInt32 v_int32)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_int32 (&value->impl, v_int32);
}

IMInt32
im_value_get_int32 (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_int32 (&value->impl);
}

void
im_value_set_uint32 (IMValue *value, IMUInt32 v_uint32)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_uint32 (&value->impl, v_uint32);
}

IMUInt32
im_value_get_uint32 (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_uint32 (&value->impl);
}

void
im_value_set_int64 (IMValue *value, IMInt64 v_int64)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_int64 (&value->impl, v_int64);
}

IMInt64
im_value_get_int64 (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_int64 (&value->impl);
}

void
im_value_set_uint64 (IMValue *value, IMUInt64 v_uint64)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_uint64 (&value->impl, v_uint64);
}

IMUInt64
im_value_get_uint64 (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_uint64 (&value->impl);
}

void
im_value_set_double (IMValue *value, IMDouble v_double)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_double (&value->impl, v_double);
}

IMDouble
im_value_get_double (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_double (&value->impl);
}

void
im_value_set_pointer (IMValue *value, IMPointer v_pointer)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_pointer (&value->impl, v_pointer);
}

IMPointer
im_value_get_pointer (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_pointer (&value->impl);
}

void
im_value_set_c_string (IMValue *value, const IMChar *v_string)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_c_string (&value->impl, v_string);
}

void
im_value_set_static_c_string  (IMValue *value, const IMChar *v_string)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_set_static_c_string (&value->impl, v_string);
}

void
im_value_take_c_string (IMValue *value, IMChar *v_string)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    im_value_impl_take_c_string (&value->impl, v_string);
}

const IMChar*
im_value_get_c_string (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_c_string (&value->impl);
}

IMChar*
im_value_dup_c_string (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_dup_c_string (&value->impl);
}

void
im_value_set_object (IMValue *value, IMPointer v_object)
{
    _im_return_if_fail (IM_IS_VALUE (value));
    _im_return_if_fail (IM_IS_OBJECT (v_object));
    im_value_impl_set_object (&value->impl, v_object);
}

IMPointer
im_value_get_object (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_get_object (&value->impl);
}

IMPointer
im_value_dup_object (const IMValue *value)
{
    _im_return_val_if_fail (IM_IS_VALUE (value), 0);
    return im_value_impl_dup_object (&value->impl);
}

IMValueImpl*
__im_value_get_impl (IMConstPointer value)
{
    return &((IMValue*)value)->impl;
}

void
__im_value_set_impl (IMPointer value, const IMValueImpl *impl)
{
    if (impl)
        ((IMValue*)value)->impl = *impl;
    else
        im_value_impl_init (&((IMValue*)value)->impl);
}

/*
vi:ts=4:nowrap:ai:expandtab
*/
